﻿/* Copyright © 2012 Gargol, Gargol at gbot dot org
   Based on CoreDC Copyright 2007 © Johan Pettersson, Fredrik Johansson, Michael Starberg, Christian Epstein.
 
This file is part of ADCCore.

ADCCore is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

ADCCore is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with ADCCore.  If not, see <http://www.gnu.org/licenses/>. */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ADCCore.Classes
{
    using Classes;
    using System.Net;
    using System.Collections;

    public class NickList : IEnumerable, IEnumerator
    {
        Dictionary<string, User> nickList = new Dictionary<string, User>();
        List<string> operators = new List<string>();
       
        public List<string> Operators
        {
            get { return operators; }
        }

        /// <summary>
        /// Find users who's usernames completely match specified string
        /// </summary>
        /// <param name="username">Complete username to look for</param>
        /// <returns>A list of users who's usernames contain the specified string</returns>
        public List<User> Find(string username)
        {
            var list = from n in nickList
                       where
                           n.Value.Username.ToLower().Equals(username.ToLower())
                       select n.Value;

            if (list.Count() > 0)
            {
                return list.ToList();
            }

            return new List<User>();
        }
        
        /// <summary>
        /// Find users who's IP-addresses match a specified IP-address
        /// </summary>
        /// <param name="ip">The IP-address to look for</param>
        /// <returns>A list of users who have the specified IP-address</returns>
        public List<User> Find(IPAddress ip)
        {
            var list = from n in nickList
                       where
                           n.Value.IP.Equals(ip)
                       select n.Value;

            if (list.Count() > 0)
            {
                return list.ToList();
            }

            return new List<User>();
        }

        public List<User> Find(IPAddress ip, int port)
        {
            var list = from n in nickList
                       where
                           n.Value.IP.Equals(ip) &&
                           n.Value.Port.Equals(port)
                       select n.Value;

            if (list.Count() > 0)
            {
                return list.ToList();
            }

            return new List<User>();
        }

        internal User Get(string SID)
        {
            try
            {
                return nickList[SID];
            }
            catch { 
                User u = new User();
                u.SID = SID;
                return u;
           }
        }

        internal bool Contains(string SID)
        {
            return nickList.Keys.Contains(SID);
        }

        /// <summary>
        /// Adds or updates a user. Returns true if new user
        /// </summary>
        internal bool Set(User user)
        {
            var exists = nickList.ContainsKey(user.SID);
            user.IsOperator = operators.Contains(user.SID);

            nickList[user.SID] = user;
           
            return (!exists);
        }
       
        internal void Remove(User user)
        {
            if (user != null)
            {
                var SID = user.SID;
               
                // removes a user, if still online...
                if (nickList.ContainsKey(SID))
                {
                    // ... but also remove from oplist if oped.
                    RemoveOperator(SID);
                    nickList.Remove(SID);
                }
            }            
        }
            
        internal void Clear()
        {
            nickList = new Dictionary<string,User>();
            operators = new List<string>();
        }
       
        internal void SetOperators(String SID)
        {
            if (!string.IsNullOrEmpty(SID))
                {
                    if (!operators.Contains(SID))
                    {
                        operators.Add(SID);
                    }
                    if (nickList.ContainsKey(SID))
                    {
                        nickList[SID].IsOperator = true;
                    }
                }     
        }

        internal void RemoveOperator(string SID)
        {
            if (operators.Contains(SID))
            {
                operators.Remove(SID);
            }
        }
       
        public int Count { get { return nickList.Count; }}
               
        public User this[string SID]
        {
            get
            {
                User u;
                if (nickList.TryGetValue(SID, out u))
                {
                    return u.Clone();
                }
               
                return null;
            }
        }

        public IEnumerator<User> GetEnumerator()
        {
            foreach (User u in nickList.Values)
            {
                yield return u.Clone();
            }
        }

        #region IEnumerator Members

        public object Current
        {
            get { throw new NotImplementedException(); }
        }

        public bool MoveNext()
        {
            throw new NotImplementedException();
        }

        public void Reset()
        {
            throw new NotImplementedException();
        }

        #endregion

        #region IEnumerable Members

        IEnumerator IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }

        #endregion
    }  
}